package com.maptasksolver.struct.heap;


/**
 * @author MDE
 *
 */
public class BinTree {
	
	private BinTree father;
	private BinTree leftSon;
	private BinTree rightSon;
	
	private int sonsLeft = 0;
	private int sonsRight = 0;
	
	private Treeable node;
	
	public BinTree(Treeable node) {
		this.node = node.clone();
	}
	
	public void connectToTreeAs(BinTree tree, BinTreeSons type) {
		this.father = tree;
		if (type == BinTreeSons.Left) {  
			tree.leftSon = this;
			father.sonsLeft = sonsLeft + sonsRight + 1;
		}
		else {
			tree.rightSon = this;
			father.sonsRight = sonsLeft + sonsRight + 1;
		}		
	}
	
	public void swapWithFather() {
		BinTree f = father;
		
		int temp = f.sonsLeft;
		f.sonsLeft = sonsLeft;
		sonsLeft = temp;
		
		temp = f.sonsRight;
		f.sonsRight = sonsRight;
		sonsRight = temp;
		
		BinTreeSons me = BinTreeSons.Right;
		BinTree son;
		if (father.leftSon == this) { 
			son = father.rightSon;
			me = BinTreeSons.Left;
		}
		else {
			son = father.leftSon;
			me = BinTreeSons.Right;
		}
		
		if (leftSon != null) {
			leftSon.connectToTreeAs(f, BinTreeSons.Left);
		} else 
			father.leftSon = null;
		if (rightSon != null) {
			rightSon.connectToTreeAs(f, BinTreeSons.Right);
		} else {
			father.rightSon = null;
		}
		
		if (son != null) {
			if (me == BinTreeSons.Left)
				son.connectToTreeAs(this, BinTreeSons.Right);
			else 
				son.connectToTreeAs(this, BinTreeSons.Left);
		} else {
			if (me == BinTreeSons.Left)
				rightSon = null;
			else
				leftSon = null;
		}
		father = father.father;
		f.connectToTreeAs(this, me);	
		
		if (father != null)
			if (father.leftSon == f)
				connectToTreeAs(father, BinTreeSons.Left);
			else
				connectToTreeAs(father, BinTreeSons.Right);	
	}
	
	public void incSon(BinTreeSons son) {
		if (BinTreeSons.Left == son)
			++sonsLeft;
		else
			++sonsRight;
	}
	
	public void deleteSon(BinTreeSons son) {
		if (BinTreeSons.Left == son) {
			leftSon = null;
			sonsLeft = 0;
		}
		else {
			rightSon = null;
			sonsRight = 0;
		}
	}

	public BinTree getFather() {
		return father;
	}

	public BinTree getLeftSon() {
		return leftSon;
	}

	public BinTree getRightSon() {
		return rightSon;
	}

	public int getSonsLeft() {
		return sonsLeft;
	}

	public int getSonsRight() {
		return sonsRight;
	}
	
	public Treeable getNode() {
		return node.clone();
	}
	
	public double getValue() {
		return node.getValue();
	}
	
	public boolean hasLeftSon() {
		return leftSon != null;
	}
	
	public boolean hasRightSon() {
		return rightSon != null;
	}
	
	public boolean hasFather() {
		return father != null;
	}

}
